Data Preparation
To create the data set used for this analysis, four data sets were
imported and manipulated. One dataset included income, one life
expectancy, one population size, and a final dataset with region. All
data sets were combined in order to create a final data set with the
following variables:
- Country
- Income
- Year
- Life Expectancy
- Region
- Population Size
This final data set will be evaluated in the following sections.
Please refer to the following code that was used in order to create this
dataset.
income <- read.csv(file="https://isarenn.github.io/irennenberg/Week5/income_per_person.csv")
life <- read.csv(file="https://isarenn.github.io/irennenberg/Week5/life_expectancy_years.csv")
population <- read.csv(file="https://isarenn.github.io/irennenberg/Week5/population_total.csv")
region <- read.csv((file="https://isarenn.github.io/irennenberg/Week5/countries_total.csv"))
##reading in files from github
##reshape income so that there are three columns, country year and income
income2 <- income %>%
gather(key="Year",
value="Income",
- geo,
na.rm=TRUE)
income3 <- income2 %>%
mutate(Year=substr(Year,2,5))
names(income3)[1]='Country'
##reshape life expectancy : country, year, life expectancy
life2 <- life %>%
gather(key="Year",
value="LifeExp",
- geo,
na.rm=TRUE)
life3 <- life2 %>%
mutate(Year=substr(Year,2,5))
names(life3)[1]='Country'
##reshaping population in the same way.
pop2 <- population %>%
gather(key="Year",
value="Population",
- geo,
na.rm=TRUE)
pop3 <- pop2 %>%
mutate(Year=substr(Year,2,5))
names(pop3)[1]='Country'
##Merge/join the above life and income sets to create one new dataset 'LifeExpIncom' with variables country,year,lifeexp and income
LifeExpIncom <- merge(income3, life3, by=c("Year","Country"))
## Merge the above dataset with the region dataset, so that the resulting dataset has income, lifeexp, population size and country region
names(region)[1]='Country'
region2 <- subset(region, select=-c(alpha.2, alpha.3, country.code, iso_3166.2, sub.region, intermediate.region, region.code, sub.region.code, intermediate.region.code))
LifeExpIncom2 <- merge(LifeExpIncom, region2, by="Country")
##Merge the above dataset with population so that there is income, lifeexp, population size country region and population size
LifeExpIncom3 <- merge(LifeExpIncom2, pop3, by=c("Year","Country"))
write.csv(LifeExpIncom3, "LifeExpIncomFinal.csv")
Data Set
Description
The final data set has 37,590 observations and 6 variables. The data
sets were retrieved from the course project data repository under the
World Life Expectancy data section. The data was collected from a public
domain.
Data For Year 2000 and
2015
In order to proceed with the data set, two datasets were created from
the following years: 2000 and 2015. The data was subset using the below
code.
d2000data <- LifeExpIncom3 %>%
filter(Year=='2000')
d2015data <- LifeExpIncom3 %>%
filter(Year=='2015')
Usage of ggplot
Scatterplot
A scatter plot of Income and Life Expectancy was created for the year
2000.
The below data plot shows that life expectancy is very low the close
the income gets to zero. As income increases, as does life expectancy.
Life expectancy increases very sharply from 0 to ~1500, where afterwards
it stabilizes as income increases.
d2000.income <- d2000data$Income
d2000.lifeexp <- d2000data$LifeExp
d2000.country <- d2000data$Country
d2000.region <- d2000data$region
d2000.pop <- d2000data$Population
ggplot(data = d2000data, mapping = aes(x = d2000.income, y = d2000.lifeexp)) +
geom_point()+
labs(
x = "Income",
y = "Life Expectancy",
title = "Association between Income and Life Expectancy",
subtitle = "Data for the Year 2000",
caption = paste("Created on", Sys.Date())) +
theme_gray()

Manipulating the ggplot
to Include the Third Numeric Variable
Now, the point size will be manipulated to display the population
size for the same year.
This dataset now shows bigger points as being higher populations. It
is seen that higher populations tend to be lower on the spectrum in
terms of income. The very high income areas show points that have a
smaller size, and therefore smaller population.
ggplot(data = d2000data, mapping = aes(x = d2000.income, y = d2000.lifeexp, size=d2000.pop)) +
geom_point()+
labs(
x = "Income",
y = "Life Expectancy",
size="Population Size",
title = "Association between Income and Life Expectancy",
subtitle = "Data for the Year 2000",
caption = paste("Created on", Sys.Date())) +
theme_gray()

Manipulating the ggplot
to Include the Categorical Region Variable
Now, the point color will be manipulated to show the 5 different
region categories for the same year. The categories are as follows:
- Africa
- Americas
- Asia
- Europe
- Oceania
This final scatter plot shows us some distinct sections for select
regions. The lower region, or Africa, tends to be localized near the
lower life expectancy and lower income. The Asia region spans the
largest income range, from being localized above the Africa cluster, to
all the way to the right (or the highest income group). Within the Asia
group, Oceania, Americas and Europe reside. Not all regions are isolated
to one area of the scatter plot. There are certain trends for areas in
which the regions reside, but there are some points that exceed that
area. For example, there are a few Africa region points that are among
the Americas/Europe/Asia points.
It is important to note that the frequency for the Oceania region is
much lower than the other regions.
ggplot(data = d2000data, mapping = aes(x = d2000.income, y = d2000.lifeexp, size=d2000.pop, color=d2000.region)) +
geom_point()+
scale_color_manual(values=c("#FFD700", "#EA5F94","#0000FF","#84FFA9","#FF8F00")) +
labs(
x = "Income",
y = "Life Expectancy",
size="Population Size",
color="Region",
title = "Association between Income and Life Expectancy",
subtitle = "Data for the Year 2000",
caption = paste("Created on", Sys.Date())) +
theme_gray()

Interactive Plot for
Year 2015
An interactive plot was created for the 2015 dataset. The interactive
scatter plot was made to display the association between life expectancy
and income.
Since population size was so large, it was sized by dividing the
population by: **~(2*log(data.pop)-11)^2.** .
d2015.income <- d2015data$Income
d2015.lifeexp <- d2015data$LifeExp
d2015.country <- d2015data$Country
d2015.region <- d2015data$region
d2015.pop <- d2015data$Population
d2015.pop2 <- d2015.pop/10000000
pal <- c("#ffbe0b", "#fb5607", "#ff006e","#8338ec","#3a86ff")
plot_ly(
data = d2015data,
x = ~d2015.income, # Horizontal axis
y = ~d2015.lifeexp, # Vertical axis
color = ~factor(d2015.region), # must be a numeric factor
colors=pal,
text = ~paste("Population Size: ", d2015.pop,
"<br>Region:", d2015.region,
"<br>Country:", d2015.country),
# Show the species in the hover text
## using the following hovertemplate() to add the information of the
## Two numerical variables to the hover text.
### Use the following hover template to display more information
hovertemplate = paste('<i><b>Life Expectancy<b></i>: %{y}',
'<br><b>Income</b>: %{x}',
'<br><b>%{text}</b>'),
alpha = 0.6,
marker = list(size = ~~(2*log(d2015.pop)-11)^2, sizeref = .05, sizemode = 'area' ),
type = "scatter",
mode = "markers",
size.mode='area',
## graphic size
width = 700,
height = 350
) %>%
layout(
### Title
title =list(text = "Income vs Life Expectancy for the Year 2015",
font = list(family = "Times New Roman", # HTML font family
size = 18,
color = "#ff006e")),
### legend
legend = list(title = list(text = 'Region',
font = list(family = "Times New Roman",
size = 14,
color = "black")),
bgcolor = "#f7f7f7",
bordercolor = "black",
groupclick = "togglegroup", # one of "toggleitem" AND "togglegroup".
orientation = "v" # Sets the orientation of the legend.
),
## Backgrounds
plot_bgcolor ='#f7f7f7',
## Axes labels
xaxis = list(
title=list(text = 'Income',
font = list(family = 'Times New Roman')),
zerolinecolor = 'gray',
zerolinewidth = 2,
gridcolor = 'white'),
yaxis = list(
title=list(text = 'Life Expectancy',
font = list(family = 'Times New Roman')),
zerolinecolor = 'purple',
zerolinewidth = 2,
gridcolor = 'white'),
## annotations
annotations = list(
x = 0.7, # between 0 and 1. 0 = left, 1 = right
y = 1.5, # between 0 and 1, 0 = bottom, 1 = top
font = list(size = 12,
color = "#ff006e"),
text = "The point size is proportional to population size.",
xref = "paper", # "container" spans the entire `width` of the
# lot. "paper" refers to the width of the
# plotting area only. yref = "paper",
# same as xref.
xanchor = "center", # horizontal alignment with respect to its x position
yanchor = "bottom", # similar to xanchor
showarrow = FALSE)
)
Animated Plot
This animated plot aids in looking at the trends over time for the
association between income and life expectancy for the entirety of the
dataset.
data.income <- LifeExpIncom3$Income
data.lifeexp <- LifeExpIncom3$LifeExp
data.country <- LifeExpIncom3$Country
data.region <- LifeExpIncom3$region
data.pop <- LifeExpIncom3$Population
data.year <- LifeExpIncom3$Year
pal.IBM <- c("#ffbe0b", "#fb5607", "#ff006e","#8338ec","#3a86ff")
pal.IBM <- setNames(pal.IBM, c("Asia", "Europe", "Africa", "Americas", "Oceania"))
df <- LifeExpIncom3
fig <- df %>%
plot_ly(
x = ~data.income,
y = ~data.lifeexp,
size = ~(2*log(data.pop)-11)^2,
color = ~data.region,
colors = pal.IBM, # custom colors
#marker = list(size = ~(log(pop)-10), sizemode = 'area'),
frame = ~data.year, # the time variable to
# to display in the hover
text = ~paste("Country:", data.country,
"<br>Continent:", data.region,
"<br>Year:", data.year,
"<br>Income:", data.income,
"<br>LifeExp:", data.lifeexp,
"<br>Population:", data.pop),
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
) %>%
layout(
title=list(text="Income vs Life Expectancy from 1800-2018",
font=list(family="Time New Roman",
size=18,
color="#ff006e")),
xaxis = list(
title=list(text = 'Income',
font = list(family = 'Times New Roman')),
gridcolor = 'white'),
yaxis = list(
title=list(text = 'Life Expectnacy',
font = list(family = 'Times New Roman')),
gridcolor = 'white')
)
fig <- fig %>% layout(
xaxis = list(
type = "log"
)
)
fig
Final Conlusions
The original data sets were manipulated to create one large dataset
with the following variables: country, income, year, life expectancy,
region and population size.
As seen with the animated scatter plot (previous section), income and
life expectancy increased over time from the years 1800-2018 (the entire
span of the data sets). There were several instances in which there were
drastic drops in the life expectancy, around the time of World Wars.
There is a relationship throughout time between life expectancy and
income.
For the three graphs created with the data from 2000, it is evident
that there is a relationship between income and life expectancy. Points
of high income and life expectancy were all smaller in size, indicating
a lower population, with the exception of a point for the Americas in
the final graph. It was found that when changing the color for region,
it was most evident that the Africa region was densely close at the
lower income and lower life expectancy area. The other four regions-
Oceania, Europe, Asia and Americas, were (for the most part) higher than
the Africa region for life expectancy and income. There were some Africa
points on the graph that were among the other regions. The Asia region
was second to Africa in that there seemed to be grouping of points in
the mid-range of the graph.
The graph showed that from the 0 to ~1500 income range, there was a
sharp increase in life expectancy. Following ~30,000 (income) the life
expectancy remains stable. Life expectancy was the lowest when income
was incredibly close to 0, and increased exponentially the farther away
from zero until the stabilization occurred.
For the interactive plot from the year 2015, there are similar
relationships in the graph. Notably, the point with the highest income
comes from Qatar, and the lowest income (and life expectancy) comes from
the Central African Republic. Similarly to the 2000 year scatter plot,
there is a sharp increase earlier in the plot, and then a leveling out,
around 20,000.
Thank you and good night!
LS0tDQp0aXRsZTogIkNvdW50cnkgQ29tcGFyaXNvbnMiDQphdXRob3I6ICJJc2FiZWxsZSBSZW5uZW5iZXJnIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIHRoZW1lOiAic3BhY2VsYWIiDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICAgDQogICAgDQotLS0gIA0KDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMzhweDsNCiAgY29sb3I6ICMwMDAwRkY7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6ICM0MWI2YzQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgxIHsNCiAgICBmb250LXNpemU6IDIycHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6ICM0MWI2YzQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCjwvc3R5bGU+DQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpvcHRpb25zKHJlcG9zID0gbGlzdChDUkFOPSJodHRwOi8vY3Jhbi5yc3R1ZGlvLmNvbS8iKSkNCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgiY293cGxvdCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikNCiAgIGxpYnJhcnkoY293cGxvdCkNCn0NCmlmICghcmVxdWlyZSgibGF0ZXgyZXhwIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImxhdGV4MmV4cCIpDQogICBsaWJyYXJ5KGxhdGV4MmV4cCkNCn0NCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogICBsaWJyYXJ5KHBsb3RseSkNCn0NCmlmICghcmVxdWlyZSgiZ2FwbWluZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdhcG1pbmRlciIpDQogICBsaWJyYXJ5KGdhcG1pbmRlcikNCn0NCmlmICghcmVxdWlyZSgicG5nIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwbmciKSAgICANCiAgICBsaWJyYXJ5KCJwbmciKQ0KfQ0KaWYgKCFyZXF1aXJlKCJSQ3VybCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiUkN1cmwiKSAgICANCiAgICBsaWJyYXJ5KCJSQ3VybCIpDQp9DQppZiAoIXJlcXVpcmUoImNvbG91cnBpY2tlciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiY29sb3VycGlja2VyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImNvbG91cnBpY2tlciIpDQp9DQppZiAoIXJlcXVpcmUoImdnYW5pbWF0ZSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dhbmltYXRlIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdnYW5pbWF0ZSIpDQp9DQppZiAoIXJlcXVpcmUoImdpZnNraSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2lmc2tpIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdpZnNraSIpDQp9DQppZiAoIXJlcXVpcmUoIm1hZ2ljayIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibWFnaWNrIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoIm1hZ2ljayIpDQp9DQppZiAoIXJlcXVpcmUoImdyRGV2aWNlcyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ3JEZXZpY2VzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdyRGV2aWNlcyIpDQp9DQppZiAoIXJlcXVpcmUoImpwZWciKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImpwZWciKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgianBlZyIpDQp9DQppZiAoIXJlcXVpcmUoImdncmlkZ2VzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3JpZGdlcyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZ3JpZGdlcyIpDQp9DQppZiAoIXJlcXVpcmUoInBseXIiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInBseXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgicGx5ciIpDQp9DQppZiAoIXJlcXVpcmUoImdnaXJhcGgiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdnaXJhcGgiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2dpcmFwaCIpDQp9DQppZiAoIXJlcXVpcmUoImhpZ2hjaGFydGVyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJoaWdoY2hhcnRlciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJoaWdoY2hhcnRlciIpDQp9DQppZiAoIXJlcXVpcmUoImZvcmVjYXN0IikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJmb3JlY2FzdCIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJmb3JlY2FzdCIpDQp9DQojIyANCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQSkNCmBgYA0KIyBEYXRhIFByZXBhcmF0aW9uDQoNClRvIGNyZWF0ZSB0aGUgZGF0YSBzZXQgdXNlZCBmb3IgdGhpcyBhbmFseXNpcywgZm91ciBkYXRhIHNldHMgd2VyZSBpbXBvcnRlZCBhbmQgbWFuaXB1bGF0ZWQuIE9uZSBkYXRhc2V0IGluY2x1ZGVkIGluY29tZSwgb25lIGxpZmUgZXhwZWN0YW5jeSwgb25lIHBvcHVsYXRpb24gc2l6ZSwgYW5kIGEgZmluYWwgZGF0YXNldCB3aXRoIHJlZ2lvbi4gQWxsIGRhdGEgc2V0cyB3ZXJlIGNvbWJpbmVkIGluIG9yZGVyIHRvIGNyZWF0ZSBhIGZpbmFsIGRhdGEgc2V0IHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6IA0KDQoqICoqQ291bnRyeSoqDQoqICoqSW5jb21lKioNCiogKipZZWFyKioNCiogKipMaWZlIEV4cGVjdGFuY3kqKg0KKiAqKlJlZ2lvbioqDQoqICoqUG9wdWxhdGlvbiBTaXplKioNCg0KVGhpcyBmaW5hbCBkYXRhIHNldCB3aWxsIGJlIGV2YWx1YXRlZCBpbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zLiBQbGVhc2UgcmVmZXIgdG8gdGhlIGZvbGxvd2luZyBjb2RlIHRoYXQgd2FzIHVzZWQgaW4gb3JkZXIgdG8gY3JlYXRlIHRoaXMgZGF0YXNldC4gDQoNCmBgYHtyfQ0KDQppbmNvbWUgPC0gcmVhZC5jc3YoZmlsZT0iaHR0cHM6Ly9pc2FyZW5uLmdpdGh1Yi5pby9pcmVubmVuYmVyZy9XZWVrNS9pbmNvbWVfcGVyX3BlcnNvbi5jc3YiKQ0KbGlmZSA8LSByZWFkLmNzdihmaWxlPSJodHRwczovL2lzYXJlbm4uZ2l0aHViLmlvL2lyZW5uZW5iZXJnL1dlZWs1L2xpZmVfZXhwZWN0YW5jeV95ZWFycy5jc3YiKQ0KcG9wdWxhdGlvbiA8LSByZWFkLmNzdihmaWxlPSJodHRwczovL2lzYXJlbm4uZ2l0aHViLmlvL2lyZW5uZW5iZXJnL1dlZWs1L3BvcHVsYXRpb25fdG90YWwuY3N2IikNCnJlZ2lvbiA8LSByZWFkLmNzdigoZmlsZT0iaHR0cHM6Ly9pc2FyZW5uLmdpdGh1Yi5pby9pcmVubmVuYmVyZy9XZWVrNS9jb3VudHJpZXNfdG90YWwuY3N2IikpDQoNCiMjcmVhZGluZyBpbiBmaWxlcyBmcm9tIGdpdGh1Yg0KDQojI3Jlc2hhcGUgaW5jb21lIHNvIHRoYXQgdGhlcmUgYXJlIHRocmVlIGNvbHVtbnMsIGNvdW50cnkgeWVhciBhbmQgaW5jb21lDQoNCmluY29tZTIgPC0gaW5jb21lICU+JQ0KICBnYXRoZXIoa2V5PSJZZWFyIiwNCiAgICAgICAgIHZhbHVlPSJJbmNvbWUiLA0KICAgICAgICAgLSBnZW8sDQogICAgICAgICBuYS5ybT1UUlVFKQ0KaW5jb21lMyA8LSBpbmNvbWUyICU+JQ0KICBtdXRhdGUoWWVhcj1zdWJzdHIoWWVhciwyLDUpKQ0KDQpuYW1lcyhpbmNvbWUzKVsxXT0nQ291bnRyeScNCg0KIyNyZXNoYXBlIGxpZmUgZXhwZWN0YW5jeSA6IGNvdW50cnksIHllYXIsIGxpZmUgZXhwZWN0YW5jeQ0KDQpsaWZlMiA8LSBsaWZlICU+JQ0KICBnYXRoZXIoa2V5PSJZZWFyIiwNCiAgICAgICAgIHZhbHVlPSJMaWZlRXhwIiwNCiAgICAgICAgIC0gZ2VvLA0KICAgICAgICAgbmEucm09VFJVRSkNCmxpZmUzIDwtIGxpZmUyICU+JQ0KICBtdXRhdGUoWWVhcj1zdWJzdHIoWWVhciwyLDUpKQ0KDQpuYW1lcyhsaWZlMylbMV09J0NvdW50cnknDQoNCiMjcmVzaGFwaW5nIHBvcHVsYXRpb24gaW4gdGhlIHNhbWUgd2F5LiANCg0KcG9wMiA8LSBwb3B1bGF0aW9uICU+JQ0KICBnYXRoZXIoa2V5PSJZZWFyIiwNCiAgICAgICAgIHZhbHVlPSJQb3B1bGF0aW9uIiwNCiAgICAgICAgIC0gZ2VvLA0KICAgICAgICAgbmEucm09VFJVRSkNCnBvcDMgPC0gcG9wMiAlPiUNCiAgbXV0YXRlKFllYXI9c3Vic3RyKFllYXIsMiw1KSkNCg0KbmFtZXMocG9wMylbMV09J0NvdW50cnknDQoNCiMjTWVyZ2Uvam9pbiB0aGUgYWJvdmUgbGlmZSBhbmQgaW5jb21lIHNldHMgdG8gY3JlYXRlIG9uZSBuZXcgZGF0YXNldCAnTGlmZUV4cEluY29tJyB3aXRoIHZhcmlhYmxlcyBjb3VudHJ5LHllYXIsbGlmZWV4cCBhbmQgaW5jb21lDQoNCkxpZmVFeHBJbmNvbSA8LSBtZXJnZShpbmNvbWUzLCBsaWZlMywgYnk9YygiWWVhciIsIkNvdW50cnkiKSkNCg0KIyMgTWVyZ2UgdGhlIGFib3ZlIGRhdGFzZXQgd2l0aCB0aGUgcmVnaW9uIGRhdGFzZXQsIHNvIHRoYXQgdGhlIHJlc3VsdGluZyBkYXRhc2V0IGhhcyBpbmNvbWUsIGxpZmVleHAsIHBvcHVsYXRpb24gc2l6ZSBhbmQgY291bnRyeSByZWdpb24NCg0KbmFtZXMocmVnaW9uKVsxXT0nQ291bnRyeScNCnJlZ2lvbjIgPC0gc3Vic2V0KHJlZ2lvbiwgc2VsZWN0PS1jKGFscGhhLjIsIGFscGhhLjMsIGNvdW50cnkuY29kZSwgaXNvXzMxNjYuMiwgc3ViLnJlZ2lvbiwgaW50ZXJtZWRpYXRlLnJlZ2lvbiwgcmVnaW9uLmNvZGUsIHN1Yi5yZWdpb24uY29kZSwgaW50ZXJtZWRpYXRlLnJlZ2lvbi5jb2RlKSkNCg0KTGlmZUV4cEluY29tMiA8LSBtZXJnZShMaWZlRXhwSW5jb20sIHJlZ2lvbjIsIGJ5PSJDb3VudHJ5IikNCg0KIyNNZXJnZSB0aGUgYWJvdmUgZGF0YXNldCB3aXRoIHBvcHVsYXRpb24gc28gdGhhdCB0aGVyZSBpcyBpbmNvbWUsIGxpZmVleHAsIHBvcHVsYXRpb24gc2l6ZSBjb3VudHJ5IHJlZ2lvbiBhbmQgcG9wdWxhdGlvbiBzaXplDQoNCkxpZmVFeHBJbmNvbTMgPC0gbWVyZ2UoTGlmZUV4cEluY29tMiwgcG9wMywgYnk9YygiWWVhciIsIkNvdW50cnkiKSkNCg0Kd3JpdGUuY3N2KExpZmVFeHBJbmNvbTMsICJMaWZlRXhwSW5jb21GaW5hbC5jc3YiKQ0KDQpgYGANCg0KIyBEYXRhIFNldCBEZXNjcmlwdGlvbg0KDQpUaGUgZmluYWwgZGF0YSBzZXQgaGFzIDM3LDU5MCBvYnNlcnZhdGlvbnMgYW5kIDYgdmFyaWFibGVzLiBUaGUgZGF0YSBzZXRzIHdlcmUgcmV0cmlldmVkIGZyb20gdGhlIGNvdXJzZSBwcm9qZWN0IGRhdGEgcmVwb3NpdG9yeSB1bmRlciB0aGUgV29ybGQgTGlmZSBFeHBlY3RhbmN5IGRhdGEgc2VjdGlvbi4gVGhlIGRhdGEgd2FzIGNvbGxlY3RlZCBmcm9tIGEgcHVibGljIGRvbWFpbi4gDQoNCiMgRGF0YSBGb3IgWWVhciAyMDAwIGFuZCAyMDE1DQoNCkluIG9yZGVyIHRvIHByb2NlZWQgd2l0aCB0aGUgZGF0YSBzZXQsIHR3byBkYXRhc2V0cyB3ZXJlIGNyZWF0ZWQgZnJvbSB0aGUgZm9sbG93aW5nIHllYXJzOiAyMDAwIGFuZCAyMDE1LiBUaGUgZGF0YSB3YXMgc3Vic2V0IHVzaW5nIHRoZSBiZWxvdyBjb2RlLiANCg0KYGBge3J9DQoNCmQyMDAwZGF0YSA8LSBMaWZlRXhwSW5jb20zICU+JQ0KICBmaWx0ZXIoWWVhcj09JzIwMDAnKQ0KDQpkMjAxNWRhdGEgPC0gTGlmZUV4cEluY29tMyAlPiUNCiAgZmlsdGVyKFllYXI9PScyMDE1JykNCg0KYGBgDQoNCiMgVXNhZ2Ugb2YgZ2dwbG90IFNjYXR0ZXJwbG90DQoNCkEgc2NhdHRlciBwbG90IG9mIEluY29tZSBhbmQgTGlmZSBFeHBlY3RhbmN5IHdhcyBjcmVhdGVkIGZvciB0aGUgeWVhciAyMDAwLiANCg0KVGhlIGJlbG93IGRhdGEgcGxvdCBzaG93cyB0aGF0IGxpZmUgZXhwZWN0YW5jeSBpcyB2ZXJ5IGxvdyB0aGUgY2xvc2UgdGhlIGluY29tZSBnZXRzIHRvIHplcm8uIEFzIGluY29tZSBpbmNyZWFzZXMsIGFzIGRvZXMgbGlmZSBleHBlY3RhbmN5LiBMaWZlIGV4cGVjdGFuY3kgaW5jcmVhc2VzIHZlcnkgc2hhcnBseSBmcm9tIDAgdG8gfjE1MDAsIHdoZXJlIGFmdGVyd2FyZHMgaXQgc3RhYmlsaXplcyBhcyBpbmNvbWUgaW5jcmVhc2VzLiANCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcid9DQpkMjAwMC5pbmNvbWUgPC0gZDIwMDBkYXRhJEluY29tZQ0KZDIwMDAubGlmZWV4cCA8LSBkMjAwMGRhdGEkTGlmZUV4cA0KZDIwMDAuY291bnRyeSA8LSBkMjAwMGRhdGEkQ291bnRyeQ0KZDIwMDAucmVnaW9uIDwtIGQyMDAwZGF0YSRyZWdpb24NCmQyMDAwLnBvcCA8LSBkMjAwMGRhdGEkUG9wdWxhdGlvbg0KDQpnZ3Bsb3QoZGF0YSA9IGQyMDAwZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gZDIwMDAuaW5jb21lLCB5ID0gZDIwMDAubGlmZWV4cCkpICsNCiAgZ2VvbV9wb2ludCgpKw0KICBsYWJzKA0KICAgICAgICAgICAgICAgICB4ID0gIkluY29tZSIsDQogICAgICAgICAgICAgICAgIHkgPSAiTGlmZSBFeHBlY3RhbmN5IiwNCiAgICAgICAgICAgICAgICAgdGl0bGUgPSAiQXNzb2NpYXRpb24gYmV0d2VlbiBJbmNvbWUgYW5kIExpZmUgRXhwZWN0YW5jeSIsDQogICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIkRhdGEgZm9yIHRoZSBZZWFyIDIwMDAiLA0KICAgICAgICAgICAgICAgICBjYXB0aW9uID0gcGFzdGUoIkNyZWF0ZWQgb24iLCBTeXMuRGF0ZSgpKSkgKw0KICAgICAgICAgICAgIHRoZW1lX2dyYXkoKSANCmBgYA0KDQojIE1hbmlwdWxhdGluZyB0aGUgZ2dwbG90IHRvIEluY2x1ZGUgdGhlIFRoaXJkIE51bWVyaWMgVmFyaWFibGUNCg0KTm93LCB0aGUgcG9pbnQgc2l6ZSB3aWxsIGJlIG1hbmlwdWxhdGVkIHRvIGRpc3BsYXkgdGhlIHBvcHVsYXRpb24gc2l6ZSBmb3IgdGhlIHNhbWUgeWVhci4NCg0KVGhpcyBkYXRhc2V0IG5vdyBzaG93cyBiaWdnZXIgcG9pbnRzIGFzIGJlaW5nIGhpZ2hlciBwb3B1bGF0aW9ucy4gSXQgaXMgc2VlbiB0aGF0IGhpZ2hlciBwb3B1bGF0aW9ucyB0ZW5kIHRvIGJlIGxvd2VyIG9uIHRoZSBzcGVjdHJ1bSBpbiB0ZXJtcyBvZiBpbmNvbWUuIFRoZSB2ZXJ5IGhpZ2ggaW5jb21lIGFyZWFzIHNob3cgcG9pbnRzIHRoYXQgaGF2ZSBhIHNtYWxsZXIgc2l6ZSwgYW5kIHRoZXJlZm9yZSBzbWFsbGVyIHBvcHVsYXRpb24uIA0KDQpgYGB7ciwgZmlnLmFsaWduPSdjZW50ZXInfQ0KDQpnZ3Bsb3QoZGF0YSA9IGQyMDAwZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gZDIwMDAuaW5jb21lLCB5ID0gZDIwMDAubGlmZWV4cCwgc2l6ZT1kMjAwMC5wb3ApKSArDQogIGdlb21fcG9pbnQoKSsNCiAgbGFicygNCiAgICAgICAgICAgICAgICAgeCA9ICJJbmNvbWUiLA0KICAgICAgICAgICAgICAgICB5ID0gIkxpZmUgRXhwZWN0YW5jeSIsDQogICAgICAgICAgICAgICAgIHNpemU9IlBvcHVsYXRpb24gU2l6ZSIsDQogICAgICAgICAgICAgICAgIHRpdGxlID0gIkFzc29jaWF0aW9uIGJldHdlZW4gSW5jb21lIGFuZCBMaWZlIEV4cGVjdGFuY3kiLA0KICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJEYXRhIGZvciB0aGUgWWVhciAyMDAwIiwNCiAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHBhc3RlKCJDcmVhdGVkIG9uIiwgU3lzLkRhdGUoKSkpICsNCiAgICAgICAgICAgICB0aGVtZV9ncmF5KCkgDQoNCmBgYA0KDQojIE1hbmlwdWxhdGluZyB0aGUgZ2dwbG90IHRvIEluY2x1ZGUgdGhlIENhdGVnb3JpY2FsIFJlZ2lvbiBWYXJpYWJsZQ0KDQpOb3csIHRoZSBwb2ludCBjb2xvciB3aWxsIGJlIG1hbmlwdWxhdGVkIHRvIHNob3cgdGhlIDUgZGlmZmVyZW50IHJlZ2lvbiBjYXRlZ29yaWVzIGZvciB0aGUgc2FtZSB5ZWFyLiBUaGUgY2F0ZWdvcmllcyBhcmUgYXMgZm9sbG93czogDQoNCiogKipBZnJpY2EqKg0KKiAqKkFtZXJpY2FzKioNCiogKipBc2lhKioNCiogKipFdXJvcGUqKg0KKiAqKk9jZWFuaWEqKiANCg0KVGhpcyBmaW5hbCBzY2F0dGVyIHBsb3Qgc2hvd3MgdXMgc29tZSBkaXN0aW5jdCBzZWN0aW9ucyBmb3Igc2VsZWN0IHJlZ2lvbnMuIFRoZSBsb3dlciByZWdpb24sIG9yIEFmcmljYSwgdGVuZHMgdG8gYmUgbG9jYWxpemVkIG5lYXIgdGhlIGxvd2VyIGxpZmUgZXhwZWN0YW5jeSBhbmQgbG93ZXIgaW5jb21lLiBUaGUgQXNpYSByZWdpb24gc3BhbnMgdGhlIGxhcmdlc3QgaW5jb21lIHJhbmdlLCBmcm9tIGJlaW5nIGxvY2FsaXplZCBhYm92ZSB0aGUgQWZyaWNhIGNsdXN0ZXIsIHRvIGFsbCB0aGUgd2F5IHRvIHRoZSByaWdodCAob3IgdGhlIGhpZ2hlc3QgaW5jb21lIGdyb3VwKS4gV2l0aGluIHRoZSBBc2lhIGdyb3VwLCBPY2VhbmlhLCBBbWVyaWNhcyBhbmQgRXVyb3BlIHJlc2lkZS4gTm90IGFsbCByZWdpb25zIGFyZSBpc29sYXRlZCB0byBvbmUgYXJlYSBvZiB0aGUgc2NhdHRlciBwbG90LiBUaGVyZSBhcmUgY2VydGFpbiB0cmVuZHMgZm9yIGFyZWFzIGluIHdoaWNoIHRoZSByZWdpb25zIHJlc2lkZSwgYnV0IHRoZXJlIGFyZSBzb21lIHBvaW50cyB0aGF0IGV4Y2VlZCB0aGF0IGFyZWEuIEZvciBleGFtcGxlLCB0aGVyZSBhcmUgYSBmZXcgQWZyaWNhIHJlZ2lvbiBwb2ludHMgdGhhdCBhcmUgYW1vbmcgdGhlIEFtZXJpY2FzL0V1cm9wZS9Bc2lhIHBvaW50cy4gDQoNCkl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlIGZyZXF1ZW5jeSBmb3IgdGhlIE9jZWFuaWEgcmVnaW9uIGlzIG11Y2ggbG93ZXIgdGhhbiB0aGUgb3RoZXIgcmVnaW9ucy4gDQoNCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcid9DQoNCmdncGxvdChkYXRhID0gZDIwMDBkYXRhLCBtYXBwaW5nID0gYWVzKHggPSBkMjAwMC5pbmNvbWUsIHkgPSBkMjAwMC5saWZlZXhwLCBzaXplPWQyMDAwLnBvcCwgY29sb3I9ZDIwMDAucmVnaW9uKSkgKw0KICBnZW9tX3BvaW50KCkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0ZGRDcwMCIsICIjRUE1Rjk0IiwiIzAwMDBGRiIsIiM4NEZGQTkiLCIjRkY4RjAwIikpICsNCiAgbGFicygNCiAgICAgICAgICAgICAgICAgeCA9ICJJbmNvbWUiLA0KICAgICAgICAgICAgICAgICB5ID0gIkxpZmUgRXhwZWN0YW5jeSIsDQogICAgICAgICAgICAgICAgIHNpemU9IlBvcHVsYXRpb24gU2l6ZSIsDQogICAgICAgICAgICAgICAgIGNvbG9yPSJSZWdpb24iLA0KICAgICAgICAgICAgICAgICB0aXRsZSA9ICJBc3NvY2lhdGlvbiBiZXR3ZWVuIEluY29tZSBhbmQgTGlmZSBFeHBlY3RhbmN5IiwNCiAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiRGF0YSBmb3IgdGhlIFllYXIgMjAwMCIsDQogICAgICAgICAgICAgICAgIGNhcHRpb24gPSBwYXN0ZSgiQ3JlYXRlZCBvbiIsIFN5cy5EYXRlKCkpKSArDQogICAgICAgICAgICAgdGhlbWVfZ3JheSgpIA0KDQpgYGANCg0KIyBJbnRlcmFjdGl2ZSBQbG90IGZvciBZZWFyIDIwMTUNCg0KQW4gaW50ZXJhY3RpdmUgcGxvdCB3YXMgY3JlYXRlZCBmb3IgdGhlIDIwMTUgZGF0YXNldC4gVGhlIGludGVyYWN0aXZlIHNjYXR0ZXIgcGxvdCB3YXMgbWFkZSB0byBkaXNwbGF5IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgaW5jb21lLiANCg0KU2luY2UgcG9wdWxhdGlvbiBzaXplIHdhcyBzbyBsYXJnZSwgaXQgd2FzIHNpemVkIGJ5IGRpdmlkaW5nIHRoZSBwb3B1bGF0aW9uIGJ5OiAqKn4oMipsb2coZGF0YS5wb3ApLTExKV4yLioqIC4NCg0KYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9Nn0NCmQyMDE1LmluY29tZSA8LSBkMjAxNWRhdGEkSW5jb21lDQpkMjAxNS5saWZlZXhwIDwtIGQyMDE1ZGF0YSRMaWZlRXhwDQpkMjAxNS5jb3VudHJ5IDwtIGQyMDE1ZGF0YSRDb3VudHJ5DQpkMjAxNS5yZWdpb24gPC0gZDIwMTVkYXRhJHJlZ2lvbg0KZDIwMTUucG9wIDwtIGQyMDE1ZGF0YSRQb3B1bGF0aW9uDQpkMjAxNS5wb3AyIDwtIGQyMDE1LnBvcC8xMDAwMDAwMA0KcGFsIDwtIGMoIiNmZmJlMGIiLCAiI2ZiNTYwNyIsICIjZmYwMDZlIiwiIzgzMzhlYyIsIiMzYTg2ZmYiKQ0KDQpwbG90X2x5KA0KICAgIGRhdGEgPSBkMjAxNWRhdGEsDQogICAgeCA9IH5kMjAxNS5pbmNvbWUsICAjIEhvcml6b250YWwgYXhpcyANCiAgICB5ID0gfmQyMDE1LmxpZmVleHAsICAgIyBWZXJ0aWNhbCBheGlzIA0KICAgIGNvbG9yID0gfmZhY3RvcihkMjAxNS5yZWdpb24pLCAgIyBtdXN0IGJlIGEgbnVtZXJpYyBmYWN0b3INCiAgICBjb2xvcnM9cGFsLA0KICAgIHRleHQgPSB+cGFzdGUoIlBvcHVsYXRpb24gU2l6ZTogIiwgZDIwMTUucG9wLA0KICAgICAgICAgICAgICAgICAgICI8YnI+UmVnaW9uOiIsIGQyMDE1LnJlZ2lvbiwNCiAgICAgICAgICAgICAgICAgICAiPGJyPkNvdW50cnk6IiwgZDIwMTUuY291bnRyeSksIA0KICAgICAjIFNob3cgdGhlIHNwZWNpZXMgaW4gdGhlIGhvdmVyIHRleHQNCiAgICAgIyMgdXNpbmcgdGhlIGZvbGxvd2luZyBob3ZlcnRlbXBsYXRlKCkgdG8gYWRkIHRoZSBpbmZvcm1hdGlvbiBvZiB0aGUNCiAgICAgIyMgVHdvIG51bWVyaWNhbCB2YXJpYWJsZXMgdG8gdGhlIGhvdmVyIHRleHQuDQogICAgICMjIyBVc2UgdGhlIGZvbGxvd2luZyBob3ZlciB0ZW1wbGF0ZSB0byBkaXNwbGF5IG1vcmUgaW5mb3JtYXRpb24NCiAgICAgaG92ZXJ0ZW1wbGF0ZSA9IHBhc3RlKCc8aT48Yj5MaWZlIEV4cGVjdGFuY3k8Yj48L2k+OiAle3l9JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+PGI+SW5jb21lPC9iPjogICV7eH0nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj48Yj4le3RleHR9PC9iPicpLA0KICAgICBhbHBoYSAgPSAwLjYsDQogICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IH5+KDIqbG9nKGQyMDE1LnBvcCktMTEpXjIsIHNpemVyZWYgPSAuMDUsIHNpemVtb2RlID0gJ2FyZWEnICksDQogICAgIHR5cGUgPSAic2NhdHRlciIsDQogICAgIG1vZGUgPSAibWFya2VycyIsDQogICAgIHNpemUubW9kZT0nYXJlYScsDQogICAgICMjIGdyYXBoaWMgc2l6ZQ0KICAgICB3aWR0aCA9IDcwMCwNCiAgICAgaGVpZ2h0ID0gMzUwDQogICApICU+JQ0KICAgIGxheW91dCggIA0KICAgICAgIyMjIFRpdGxlIA0KICAgICAgdGl0bGUgPWxpc3QodGV4dCA9ICJJbmNvbWUgdnMgTGlmZSBFeHBlY3RhbmN5IGZvciB0aGUgWWVhciAyMDE1IiwgDQogICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIiwgICMgSFRNTCBmb250IGZhbWlseSAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxOCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjZmYwMDZlIikpLCANCiAgICAgICMjIyBsZWdlbmQNCiAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQgPSAnUmVnaW9uJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSksDQogICAgICAgICAgICAgICAgICAgIGJnY29sb3IgPSAiI2Y3ZjdmNyIsDQogICAgICAgICAgICAgICAgICAgIGJvcmRlcmNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBjbGljayA9ICJ0b2dnbGVncm91cCIsICAjIG9uZSBvZiAgInRvZ2dsZWl0ZW0iIEFORCAidG9nZ2xlZ3JvdXAiLg0KICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiA9ICJ2IiAgIyBTZXRzIHRoZSBvcmllbnRhdGlvbiBvZiB0aGUgbGVnZW5kLg0KICAgICAgICAgICAgICAgICAgICApLA0KICAgICAgIyMgQmFja2dyb3VuZHMNCiAgICAgIHBsb3RfYmdjb2xvciA9JyNmN2Y3ZjcnLCANCiAgICAgICMjIEF4ZXMgbGFiZWxzDQogICAgICAgICAgICAgeGF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0luY29tZScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmVjb2xvciA9ICdncmF5JywgDQogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLCANCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJyksIA0KICAgICAgICAgICAgeWF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0xpZmUgRXhwZWN0YW5jeScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmVjb2xvciA9ICdwdXJwbGUnLCANCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmV3aWR0aCA9IDIsIA0KICAgICAgICAgICAgICAgICAgICBncmlkY29sb3IgPSAnd2hpdGUnKSwNCiAgICAgICAjIyBhbm5vdGF0aW9ucw0KICAgICAgIGFubm90YXRpb25zID0gbGlzdCggIA0KICAgICAgICAgICAgICAgICAgICAgeCA9IDAuNywgICAjIGJldHdlZW4gMCBhbmQgMS4gMCA9IGxlZnQsIDEgPSByaWdodA0KICAgICAgICAgICAgICAgICAgICAgeSA9IDEuNSwgICAjIGJldHdlZW4gMCBhbmQgMSwgMCA9IGJvdHRvbSwgMSA9IHRvcA0KICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDEyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiI2ZmMDA2ZSIpLCAgIA0KICAgICAgICAgICAgICAgICAgdGV4dCA9ICJUaGUgcG9pbnQgc2l6ZSBpcyBwcm9wb3J0aW9uYWwgdG8gcG9wdWxhdGlvbiBzaXplLiIsICAgDQogICAgICAgICAgICAgICAgICB4cmVmID0gInBhcGVyIiwgICMgImNvbnRhaW5lciIgc3BhbnMgdGhlIGVudGlyZSBgd2lkdGhgIG9mIHRoZSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgbG90LiAicGFwZXIiIHJlZmVycyB0byB0aGUgd2lkdGggb2YgdGhlIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICBwbG90dGluZyBhcmVhIG9ubHkuIHlyZWYgPSAicGFwZXIiLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIHNhbWUgYXMgeHJlZi4NCiAgICAgICAgICAgICAgIHhhbmNob3IgPSAiY2VudGVyIiwgIyAgaG9yaXpvbnRhbCBhbGlnbm1lbnQgd2l0aCByZXNwZWN0IHRvIGl0cyB4IHBvc2l0aW9uDQogICAgICAgICAgICAgICB5YW5jaG9yID0gImJvdHRvbSIsICMgIHNpbWlsYXIgdG8geGFuY2hvciAgDQogICAgICAgICAgICAgc2hvd2Fycm93ID0gRkFMU0UpDQogICAgKQ0KYGBgDQoNCiMgQW5pbWF0ZWQgUGxvdA0KDQpUaGlzIGFuaW1hdGVkIHBsb3QgYWlkcyBpbiBsb29raW5nIGF0IHRoZSB0cmVuZHMgb3ZlciB0aW1lIGZvciB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBpbmNvbWUgYW5kIGxpZmUgZXhwZWN0YW5jeSBmb3IgdGhlIGVudGlyZXR5IG9mIHRoZSBkYXRhc2V0LiANCg0KYGBge3J9DQoNCmRhdGEuaW5jb21lIDwtIExpZmVFeHBJbmNvbTMkSW5jb21lDQpkYXRhLmxpZmVleHAgPC0gTGlmZUV4cEluY29tMyRMaWZlRXhwDQpkYXRhLmNvdW50cnkgPC0gTGlmZUV4cEluY29tMyRDb3VudHJ5DQpkYXRhLnJlZ2lvbiA8LSBMaWZlRXhwSW5jb20zJHJlZ2lvbg0KZGF0YS5wb3AgPC0gTGlmZUV4cEluY29tMyRQb3B1bGF0aW9uDQpkYXRhLnllYXIgPC0gTGlmZUV4cEluY29tMyRZZWFyDQpwYWwuSUJNIDwtIGMoIiNmZmJlMGIiLCAiI2ZiNTYwNyIsICIjZmYwMDZlIiwiIzgzMzhlYyIsIiMzYTg2ZmYiKQ0KcGFsLklCTSA8LSBzZXROYW1lcyhwYWwuSUJNLCBjKCJBc2lhIiwgIkV1cm9wZSIsICJBZnJpY2EiLCAiQW1lcmljYXMiLCAiT2NlYW5pYSIpKQ0KDQpkZiA8LSBMaWZlRXhwSW5jb20zIA0KZmlnIDwtIGRmICU+JQ0KICBwbG90X2x5KA0KICAgIHggPSB+ZGF0YS5pbmNvbWUsIA0KICAgIHkgPSB+ZGF0YS5saWZlZXhwLCANCiAgICBzaXplID0gfigyKmxvZyhkYXRhLnBvcCktMTEpXjIsDQogICAgY29sb3IgPSB+ZGF0YS5yZWdpb24sIA0KICAgIGNvbG9ycyA9IHBhbC5JQk0sICAgIyBjdXN0b20gY29sb3JzDQogICAgI21hcmtlciA9IGxpc3Qoc2l6ZSA9IH4obG9nKHBvcCktMTApLCAgc2l6ZW1vZGUgPSAnYXJlYScpLA0KICAgIGZyYW1lID0gfmRhdGEueWVhciwgICAgICAjIHRoZSB0aW1lIHZhcmlhYmxlIHRvDQogICAgIyB0byBkaXNwbGF5IGluIHRoZSBob3Zlcg0KICAgIHRleHQgPSB+cGFzdGUoIkNvdW50cnk6IiwgZGF0YS5jb3VudHJ5LA0KICAgICAgICAgICAgICAgICAgIjxicj5Db250aW5lbnQ6IiwgZGF0YS5yZWdpb24sDQogICAgICAgICAgICAgICAgICAiPGJyPlllYXI6IiwgZGF0YS55ZWFyLA0KICAgICAgICAgICAgICAgICAgIjxicj5JbmNvbWU6IiwgZGF0YS5pbmNvbWUsDQogICAgICAgICAgICAgICAgICAiPGJyPkxpZmVFeHA6IiwgZGF0YS5saWZlZXhwLA0KICAgICAgICAgICAgICAgICAgIjxicj5Qb3B1bGF0aW9uOiIsIGRhdGEucG9wKSwNCiAgICBob3ZlcmluZm8gPSAidGV4dCIsDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ21hcmtlcnMnDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZT1saXN0KHRleHQ9IkluY29tZSB2cyBMaWZlIEV4cGVjdGFuY3kgZnJvbSAxODAwLTIwMTgiLA0KICAgICAgICAgICAgICAgZm9udD1saXN0KGZhbWlseT0iVGltZSBOZXcgUm9tYW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9MTgsDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9IiNmZjAwNmUiKSksDQogICAgeGF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0luY29tZScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJyksIA0KICAgICAgICAgICAgeWF4aXMgPSBsaXN0KCANCiAgICAgICAgICAgICAgICAgICAgdGl0bGU9bGlzdCh0ZXh0ID0gJ0xpZmUgRXhwZWN0bmFjeScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ1RpbWVzIE5ldyBSb21hbicpKSwNCiAgICAgICAgICAgICAgICAgICAgZ3JpZGNvbG9yID0gJ3doaXRlJykNCiAgKQ0KZmlnIDwtIGZpZyAlPiUgbGF5b3V0KA0KICAgIHhheGlzID0gbGlzdCgNCiAgICAgIHR5cGUgPSAibG9nIg0KICAgICkNCiAgKQ0KDQpmaWcNCmBgYA0KDQojIEZpbmFsIENvbmx1c2lvbnMgDQoNClRoZSBvcmlnaW5hbCBkYXRhIHNldHMgd2VyZSBtYW5pcHVsYXRlZCB0byBjcmVhdGUgb25lIGxhcmdlIGRhdGFzZXQgd2l0aCB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczogY291bnRyeSwgaW5jb21lLCB5ZWFyLCBsaWZlIGV4cGVjdGFuY3ksIHJlZ2lvbiBhbmQgcG9wdWxhdGlvbiBzaXplLiANCg0KQXMgc2VlbiB3aXRoIHRoZSBhbmltYXRlZCBzY2F0dGVyIHBsb3QgKHByZXZpb3VzIHNlY3Rpb24pLCBpbmNvbWUgYW5kIGxpZmUgZXhwZWN0YW5jeSBpbmNyZWFzZWQgb3ZlciB0aW1lIGZyb20gdGhlIHllYXJzIDE4MDAtMjAxOCAodGhlIGVudGlyZSBzcGFuIG9mIHRoZSBkYXRhIHNldHMpLiBUaGVyZSB3ZXJlIHNldmVyYWwgaW5zdGFuY2VzIGluIHdoaWNoIHRoZXJlIHdlcmUgZHJhc3RpYyBkcm9wcyBpbiB0aGUgbGlmZSBleHBlY3RhbmN5LCBhcm91bmQgdGhlIHRpbWUgb2YgV29ybGQgV2Fycy4gVGhlcmUgaXMgYSByZWxhdGlvbnNoaXAgdGhyb3VnaG91dCB0aW1lIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBpbmNvbWUuICANCg0KRm9yIHRoZSB0aHJlZSBncmFwaHMgY3JlYXRlZCB3aXRoIHRoZSBkYXRhIGZyb20gMjAwMCwgaXQgaXMgZXZpZGVudCB0aGF0IHRoZXJlIGlzIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gaW5jb21lIGFuZCBsaWZlIGV4cGVjdGFuY3kuIFBvaW50cyBvZiBoaWdoIGluY29tZSBhbmQgbGlmZSBleHBlY3RhbmN5IHdlcmUgYWxsIHNtYWxsZXIgaW4gc2l6ZSwgaW5kaWNhdGluZyBhIGxvd2VyIHBvcHVsYXRpb24sIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiBhIHBvaW50IGZvciB0aGUgQW1lcmljYXMgaW4gdGhlIGZpbmFsIGdyYXBoLiBJdCB3YXMgZm91bmQgdGhhdCB3aGVuIGNoYW5naW5nIHRoZSBjb2xvciBmb3IgcmVnaW9uLCBpdCB3YXMgbW9zdCBldmlkZW50IHRoYXQgdGhlIEFmcmljYSByZWdpb24gd2FzIGRlbnNlbHkgY2xvc2UgYXQgdGhlIGxvd2VyIGluY29tZSBhbmQgbG93ZXIgbGlmZSBleHBlY3RhbmN5IGFyZWEuIFRoZSBvdGhlciBmb3VyIHJlZ2lvbnMtIE9jZWFuaWEsIEV1cm9wZSwgQXNpYSBhbmQgQW1lcmljYXMsIHdlcmUgKGZvciB0aGUgbW9zdCBwYXJ0KSBoaWdoZXIgdGhhbiB0aGUgQWZyaWNhIHJlZ2lvbiBmb3IgbGlmZSBleHBlY3RhbmN5IGFuZCBpbmNvbWUuIFRoZXJlIHdlcmUgc29tZSBBZnJpY2EgcG9pbnRzIG9uIHRoZSBncmFwaCB0aGF0IHdlcmUgYW1vbmcgdGhlIG90aGVyIHJlZ2lvbnMuIFRoZSBBc2lhIHJlZ2lvbiB3YXMgc2Vjb25kIHRvIEFmcmljYSBpbiB0aGF0IHRoZXJlIHNlZW1lZCB0byBiZSBncm91cGluZyBvZiBwb2ludHMgaW4gdGhlIG1pZC1yYW5nZSBvZiB0aGUgZ3JhcGguIA0KDQpUaGUgZ3JhcGggc2hvd2VkIHRoYXQgZnJvbSB0aGUgMCB0byB+MTUwMCBpbmNvbWUgcmFuZ2UsIHRoZXJlIHdhcyBhIHNoYXJwIGluY3JlYXNlIGluIGxpZmUgZXhwZWN0YW5jeS4gRm9sbG93aW5nIH4zMCwwMDAgKGluY29tZSkgdGhlIGxpZmUgZXhwZWN0YW5jeSByZW1haW5zIHN0YWJsZS4gTGlmZSBleHBlY3RhbmN5IHdhcyB0aGUgbG93ZXN0IHdoZW4gaW5jb21lIHdhcyBpbmNyZWRpYmx5IGNsb3NlIHRvIDAsIGFuZCBpbmNyZWFzZWQgZXhwb25lbnRpYWxseSB0aGUgZmFydGhlciBhd2F5IGZyb20gemVybyB1bnRpbCB0aGUgc3RhYmlsaXphdGlvbiBvY2N1cnJlZC4gDQoNCkZvciB0aGUgaW50ZXJhY3RpdmUgcGxvdCBmcm9tIHRoZSB5ZWFyIDIwMTUsIHRoZXJlIGFyZSBzaW1pbGFyIHJlbGF0aW9uc2hpcHMgaW4gdGhlIGdyYXBoLiBOb3RhYmx5LCB0aGUgcG9pbnQgd2l0aCB0aGUgaGlnaGVzdCBpbmNvbWUgY29tZXMgZnJvbSBRYXRhciwgYW5kIHRoZSBsb3dlc3QgaW5jb21lIChhbmQgbGlmZSBleHBlY3RhbmN5KSBjb21lcyBmcm9tIHRoZSBDZW50cmFsIEFmcmljYW4gUmVwdWJsaWMuIFNpbWlsYXJseSB0byB0aGUgMjAwMCB5ZWFyIHNjYXR0ZXIgcGxvdCwgdGhlcmUgaXMgYSBzaGFycCBpbmNyZWFzZSBlYXJsaWVyIGluIHRoZSBwbG90LCBhbmQgdGhlbiBhIGxldmVsaW5nIG91dCwgYXJvdW5kIDIwLDAwMC4gDQoNClRoYW5rIHlvdSBhbmQgZ29vZCBuaWdodCEg